package org.deltaset.desktop;

import java.util.List;
import java.util.Map;
import javax.el.ELContext;
import javax.el.ValueExpression;
import javax.faces.application.ViewHandler;
import javax.faces.component.NamingContainer;
import javax.faces.component.UIComponentBase;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import org.deltaset.faces.FacesUtils;

/**
 *
 * @author dmakariev
 */
public class DesktopNamingContainer extends UIComponentBase implements NamingContainer{

    private final static String CONTEXT_KEY = "DesktopContext_" + DesktopNamingContainer.class.getName();
    //TODO: parameter from component    
    private String defaultAppSrc;// = "/home.xhtml";   
    private DesktopHandler desktopHandler;
    
    /**
     * <p>The standard component type for this component.</p>
     */
    public static final String COMPONENT_TYPE = "org.deltaset.Desktop";


    /**
     * <p>The standard component family for this component.</p>
     */
    public static final String COMPONENT_FAMILY = "javax.faces.NamingContainer";
    
    @Override
    public String getFamily() {        
        return COMPONENT_FAMILY;
    }

    public DesktopNamingContainer getDesktop() {
        return this;
    }

    public MenuItem getMenuItem() {
        return getDesktopContext().getCurrentMenuItem();
    }

    public void setMenuItem(MenuItem menuItem) {
        getDesktopContext().setCurrentMenuItem(menuItem);
        this.setPageSrc(menuItem.getTemplateSrc());
        if (menuItem.isRefreshable()) {
            refreshViewState();
        }
    }

//    public void setMenuItem(MenuItem menuItem, String src) {
//        getDesktopContext().setCurrentMenuItem(menuItem);
//        this.setPageSrc(src);
//        refreshViewState();
//    }
    //use only where it is REALLY necessary. makes the response relatively 30 - 40% slower ! 
    //with more complex models the difference gets smaller.(1%-12%)
    private void refreshViewState() {
        final FacesContext facesContext = FacesContext.getCurrentInstance();
        final String viewId = facesContext.getViewRoot().getViewId();
        final ViewHandler handler = facesContext.getApplication().getViewHandler();
        final UIViewRoot root = handler.createView(facesContext, viewId);
        root.setViewId(viewId);
        facesContext.setViewRoot(root);
    }

    public List<MenuGroup> getMenuGroups() {
        return getCurrentApp().getMenuGroups();
    }

    public String getAppTitle() {
        return getCurrentApp().getAppTitle();
    }

    public String getAppId() {
        return getCurrentApp().getAppId();
    }

    public AppItem getCurrentApp() {
        return getDesktopContext().getCurrentApp();
    }

    public String prepareApp(AppItem currentApp) {
        final String appSrc = currentApp.getAppSrc();
        final String output = (null == appSrc) ? getDefaultAppSrc() : appSrc;
        getDesktopContext().setCurrentApp(currentApp);
        this.setMenuItem(currentApp.getDefaultMenuItem());
        return output + "?faces-redirect=true";
    }

    public List<AppItem> getTopMenu() {
        return getDesktopHandler().getTopMenu();
    }

    public String getPageSrc() {
        return getDesktopContext().getPageSrc();
    }

    public void setPageSrc(String pageSrc) {
        this.getDesktopContext().setPageSrc(pageSrc);
    }

    private String getDefaultAppSrc() {
        if (null == defaultAppSrc) {
            this.defaultAppSrc = getDefaultSrcAttributeValue();
        }
        return defaultAppSrc;
    }

    private String getDefaultSrcAttributeValue() {
        return FacesUtils.getAttribute(this, "defaultSrc");
    }

    private TopMenuProvider getTopMenuProviderAttribute() {
        final ValueExpression valueVE = this.getValueExpression("topMenuProvider");
        final ELContext currentELContext = FacesContext.getCurrentInstance().getELContext();
        final TopMenuProvider topMenuProvider = (TopMenuProvider) valueVE.getValue(currentELContext);
        if (null == topMenuProvider) {
            throw new RuntimeException(this.getClass().getName() + " not configured ! missing(or null) dependency 'topMenuProvider' of type:" + TopMenuProvider.class.getName() + ". Check the configuration of tag desktop:home");
        }
        return topMenuProvider;
    }

    private DesktopHandler getDesktopHandler() {
        if (null == desktopHandler) {
            this.desktopHandler = new DesktopHandler(getTopMenuProviderAttribute());
        }
        return desktopHandler;
    }

    private DesktopContext getDesktopContext() {
        final Map<String, Object> session = FacesUtils.getSessionMap();
        if (!session.containsKey(CONTEXT_KEY)) {
            final DesktopContext dc = getDesktopHandler().getDefaultDesktopContext();
            session.put(CONTEXT_KEY, dc);
        }
        final DesktopContext dc = (DesktopContext) session.get(CONTEXT_KEY);
        if (null == dc) {
            throw new IllegalStateException("ERROR " + CONTEXT_KEY + " cannot be NULL!");
        }
        return dc;
    }
}
